<div id="themeToggle" class="flex items-center justify-center w-10 h-10 rounded-md transition-colors hover:bg-slate/10">
  <svg class="theme_toggle_svg" width="1.2em" height="1.2em" viewBox="0 0 24 24" color="#858585" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke="currentColor">
    <mask id="myMask">
      <rect x="0" y="0" width="100%" height="100%" fill="white"></rect>
      <circle class="theme_toggle_circle1" fill="black" cx="100%" cy="0%"></circle>
    </mask>
    <circle class="theme_toggle_circle2" cx="12" cy="12" fill="#858585" mask="url(#myMask)"></circle>
    <g class="theme_toggle_g" stroke="currentColor" opacity="1">
      <line x1="12" y1="1" x2="12" y2="3"></line>
      <line x1="12" y1="21" x2="12" y2="23"></line>
      <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
      <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
      <line x1="1" y1="12" x2="3" y2="12"></line>
      <line x1="21" y1="12" x2="23" y2="12"></line>
      <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
      <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
    </g>
  </svg>
</div>

<style>
  #themeToggle {
    border: 0;
    cursor: pointer;
  }
  .theme_toggle_circle1 {
    transition: cx .5s, cy .5s;
    cx: 100%;
    cy: 0%
  }
  .theme_toggle_circle2 {
    transition: r .3s;
  }
  .theme_toggle_svg {
    transition: transform .5s cubic-bezier(0.68, -0.55, 0.27, 1.55);
    transform: rotate(90deg);
  }
 .theme_toggle_g {
    transition: opacity .5s;
    opacity: 1;
  }
  :global(html.dark) #themeToggle .theme_toggle_circle1 {
    cx: 50%;
    cy: 23%;
  }
  :global(html.dark) #themeToggle .theme_toggle_svg {
    transform: rotate(40deg);
  }
  :global(html.dark) #themeToggle .theme_toggle_g {
    opacity: 0;
  }
</style>

<script>
const themeToggle = document.getElementById('themeToggle')
const themeCircle1 = document.querySelector('.theme_toggle_circle1')
const themeCircle2 = document.querySelector('.theme_toggle_circle2')
const toogleThemeCircle = () => {
  const darkMode = document.documentElement.classList.contains('dark') ?? localStorage.getItem('theme') === 'dark'
  if (darkMode) {
    themeCircle1.setAttribute('r', '9')
    themeCircle2.setAttribute('r', '9')
  } else {
    themeCircle1.setAttribute('r', '5')
    themeCircle2.setAttribute('r', '5')
  }
}

const listenColorSchema = () => {
  const colorSchema = window.matchMedia('(prefers-color-scheme: dark)')
  colorSchema.addEventListener('change', () => {
    document.documentElement.classList.toggle('dark', colorSchema.matches)
    toogleThemeCircle()
  })
}

listenColorSchema()
toogleThemeCircle()

const handleToggleClick = ({ x, y }) => {
  const root = document.documentElement
  const isDark = root.classList.contains('dark')
  localStorage.setItem('theme', isDark ? 'light' : 'dark')

  // check if the current browser supports viewtransition API
  const isAppearanceTransition
    // @ts-expect-error: Transition API
    = document.startViewTransition
    && !window.matchMedia('(prefers-reduced-motion: reduce)').matches

  // if it is not supported, just toggle the class directly
  if (!isAppearanceTransition) {
    toogleThemeCircle()
    root.classList.toggle('dark')
  } else {
    // if it is supported, use the transition API to animate the theme change
    const endRadius = Math.hypot(
      Math.max(x, innerWidth - x),
      Math.max(y, innerHeight - y),
    )

    // @ts-expect-error: Transition API
    const transition = document.startViewTransition(() => {
      root.classList.toggle('dark')
      toogleThemeCircle()
    })
    transition.ready.then(() => {
      const clipPath = [
      `circle(0px at ${x}px ${y}px)`,
      `circle(${endRadius}px at ${x}px ${y}px)`,
      ]
      const _c = !isDark ? clipPath : [...clipPath].reverse()
      const pseudoElement = !isDark
        ? '::view-transition-new(root)'
        : '::view-transition-old(root)'
      document.documentElement.animate(
        {
          clipPath: _c,
        },
        {
          duration: 500,
          easing: 'ease-in',
          pseudoElement,
        },
      )
    })
  }
}
themeToggle.addEventListener('click', handleToggleClick)
</script>
